using logging;

// 最常用的一种单例模式
class EagerSingleton_Static_Field{
    private static EagerSingleton_Static_Field _instance = new EagerSingleton_Static_Field();
    // the constructor should be protected or private
    private EagerSingleton_Static_Field(){ }

    public static EagerSingleton_Static_Field get_instance(){ return _instance; }
}
/* 饿汉式单例的问题在于：静态成员变量是在程序运行之初就被系统创建的。
   如果对象的创建开销过大，但对象实际又一直未被使用时，静态对象的创建就没有意义 */

// 懒汉式单例模式
class LazySingleton_Static_Field{
    private static LazySingleton_Static_Field _instance;
    private LazySingleton_Static_Field(){ }

    public static LazySingleton_Static_Field get_instance(){
        if(_instance == null){
            _instance = new LazySingleton_Static_Field();  // 动态创建对象
        }
        return _instance;
    }
}
/* 懒汉式单例的问题在于：对于高并发环境时，初始化时已经有多个线程同时执行 get_instance()，
   由于判断条件为 _instance 对象的存在性，而创建对象是需要时间的。在这个时间差里，可能
   if(true)被执行了多次。
   解决方法很多：最简单的，增加一个bool量用于判断当前对象是否被创建，当然这个方式只是降低
   了风险（毕竟bool的赋值要比对象创建过程快很多）。
   更标准的方式，比如创建同步锁，限制多进程对同一变量的访问。
 */


class demo{
    static void Main(){
        // var x = EagerSingleton_Static_Field.get_instance();
        // var y = EagerSingleton_Static_Field.get_instance();

        var x = LazySingleton_Static_Field.get_instance();
        var y = LazySingleton_Static_Field.get_instance();

        // var x = Singleton_Derived.get_instance();
        // var y = Singleton_Derived.get_instance();
        // var z = Singleton_Derived.get_instance();

        if(x == y)  Log.print("They are the same.");
        else  Log.print("They are different.");
    }
}

/* // 尝试继承单例：不过看上去与创建一个新类型并组合单例没什么区别。
class Singleton_Base{
    protected static Singleton_Base _instance = new Singleton_Base();
    protected Singleton_Base(){ }

    public static Singleton_Base get_instance(){ return _instance; }
}

class Singleton_Derived: Singleton_Base{
    private bool flag = false;
    protected Singleton_Derived(): base(){ }
    protected static Singleton_Derived _instance2 = new Singleton_Derived();
    public static Singleton_Derived get_instance2(){ return _instance2; }
}
*/